package com.lwp.excel.resolver.impl;

import com.lwp.excel.annotation.Cell;
import com.lwp.excel.annotation.Font;
import com.lwp.excel.annotation.Style;
import com.lwp.excel.exception.CellDataIsNullException;
import com.lwp.excel.resolver.ExcelAble;
import com.lwp.excel.util.ExcelUtil;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;

import java.lang.reflect.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Copyright (C) @2019 GuangDong Eshore Technology Co. Ltd
 *
 * @author: Administrator
 * @version: 1.0
 * @date: 2019/8/13
 * @time: 10:09
 * @description: 解析数据
 */
public class DataExcelResolver extends HeaderExcelResolver {

    public DataExcelResolver() {
    }

    public DataExcelResolver(Class<?> group,String[] headers,String title) {
        super(group, headers ,title);
    }


    /**
     * 解析数据插入数据。
     * @param sheet
     * @param dataList
     * @param wb
     */
    public void dataResolver(HSSFSheet sheet, List<?> dataList, HSSFWorkbook wb) {
        tempHeaderMap = headerMap;
        dataResolver(sheet, dataList, wb,lastRowIndex(sheet),0,new HeaderExcelResolver(group,headers,null));
    }

    public void dataResolver(HSSFSheet sheet, List<?> dataList, HSSFWorkbook wb,int insertLastRowIndex,int insertLastCellIndex,HeaderExcelResolver headerExcelResolver) {
        for (Object data :
                dataList) {
            HSSFRow row ;
            row = sheet.getRow(insertLastRowIndex);
            if (row == null) {
                row = sheet.createRow(insertLastRowIndex);
            }
            insertLastRowIndex  = dataResolver(sheet, data, wb,row,insertLastCellIndex,countParticleValRow(data,headers),headerExcelResolver);
        }
    }


    public int dataResolver(HSSFSheet sheet, Object data, HSSFWorkbook wb, HSSFRow row,int insertLastCellIndex,int fieldRowSize,HeaderExcelResolver headerExcelResolver) {
        if (data == null) {
            throw new CellDataIsNullException("data can’t be Null");
        }
        Class clazz = data.getClass();
        Field[] fields = clazz.getDeclaredFields();//获取所有字段
        Style classStyle = (Style) clazz.getAnnotation(Style.class);
        Style style = classStyle;
        Font classFont = (Font) clazz.getAnnotation(Font.class);
        Font font = classFont;
        //int insertCellIndex = lastCellIndex(row);
        //遍历字段，解析每个字段的数据，创建每行数据。
        //int fieldRowSize = countParticleValRow(data);
        for (Field field :
                fields) {
            Cell cell = field.getAnnotation(Cell.class);
            if (classStyle == null ) {//获取style注解
                style = field.getAnnotation(Style.class);
            } else {
                Style feildStyle = field.getAnnotation(Style.class);
                if ( feildStyle != null) {
                    style = feildStyle;
                }
            }
            if (classFont == null) {
                font = field.getAnnotation(Font.class);
            } else {
                Font feildFont = field.getAnnotation(Font.class);
                if (feildFont != null) {
                    font = feildFont;
                }
            }

            if (!verifyField(field, headerExcelResolver)) {//验证没有通过
                continue;
            }
            //验证通过。
            //解析数据值
            Object value = getValue(data, field);
            if (Collection.class.isAssignableFrom(field.getType())) {//是列表集合
                Class<?> genericType = null;
                if (value == null || ((List) value).size() == 0) {
                    value = new ArrayList<>();
                    Type type = field.getGenericType();
                    if (type == null) continue;
                    //得到泛型类型的类名
                    if (type instanceof ParameterizedType) {
                        ParameterizedType parameterizedType = (ParameterizedType) type;
                        //得到泛型里的class类型对象
                        genericType = (Class<?>) parameterizedType.getActualTypeArguments()[0];
                        Object obj = null;
                        try {
                            obj = genericType.newInstance();
                            ((List) value).add(obj);
                        } catch (InstantiationException e) {
                            e.printStackTrace();
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                }
                HeaderExcelResolver itemResolver = new HeaderExcelResolver(group,headers,null);
                itemResolver.setTempHeaderMap((HashMap<String,Object>)headerExcelResolver.getTempHeaderMap().get(field.getName()));
                dataResolver(sheet, (List<?>) value, wb, row.getRowNum(),lastCellIndex(row),itemResolver);
            } else if (ExcelAble.class.isAssignableFrom(field.getType())) {//是对象。
                if (value == null) {
                    try {
                        value = field.getType().newInstance();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
                HeaderExcelResolver itemResolver = new HeaderExcelResolver(group,headers,null);
                itemResolver.setTempHeaderMap((HashMap<String,Object>)headerExcelResolver.getTempHeaderMap().get(field.getName()));
                dataResolver(sheet,value,wb,row,lastCellIndex(row),fieldRowSize ,itemResolver);
            } else {//普通字段。
                HSSFCell dataCell = null;
                int lastCellIndex = lastCellIndex(row);
                if (lastCellIndex < insertLastCellIndex) {
                    lastCellIndex = insertLastCellIndex;
                }
                dataCell = row.createCell(lastCellIndex);//创建列
                String excelVal = getExcelValue(cell, value);//对Cell注解一个全面的解析，得到的最终的value值。
                HSSFCellStyle cellStyle = getStyle(wb, style, font);
                CellRangeAddress cellRangeAddress = new CellRangeAddress(//合并单元格。
                        row.getRowNum(), // 起始行
                        row.getRowNum() + fieldRowSize - 1, // 结束行
                        lastCellIndex, // 起始列
                        lastCellIndex  // 结束列
                );
                //合并单元格。
                sheet.addMergedRegion(cellRangeAddress);
                setRangeBorder(cellStyle.getBorderTop(),cellRangeAddress,sheet,wb);
                setRangeBorderColor(cellStyle.getBottomBorderColor(), cellRangeAddress, sheet, wb);
                dataCell.setCellValue(excelVal);//给列设置值。
                if (cellStyle != null) {
                    dataCell.setCellStyle(cellStyle);//给列设置样式
                }

            }
        }
        return (row.getRowNum()+fieldRowSize);

    }


    /**
     * 通过反射获取字段的值
     * @param instance
     * @param field
     * @return
     */
    public Object  getValue(Object instance,Field field){
        Object value = null;
        Class clazz = instance.getClass();
        Method method;
        try {
            if (field.getType().equals("boolean")) {// 基本变量
                method = clazz.getMethod(ExcelUtil.getBooleanPrefix(field.getName()));
            } else {
                method = clazz.getMethod("get" + ExcelUtil.getMethodName(field.getName()));
            }
            value = method.invoke(instance);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return value;
    }


    /**
     * 将java数据改为Excel数据。
     * String format() default "yyyy-MM-dd";  时间格式化
     * String defaultValue() default "";   值为null时，的默认字符串
     * String readConverterExp() default ""; 读取内容转表达式 (如: 0=男,1=女,2=未知)
     * @param cell
     * @param javaValue
     * @return
     */
    public String getExcelValue(Cell cell,Object javaValue){
        String val = null;
        if (javaValue == null) {//javaVal = null 显示默认数据
            val = cell.defaultValue();
        } else {
            CellAnnotationResolver<Cell> cellCellAnnotationResolver = new CellAnnotationResolver<>();
            if (javaValue instanceof Date) {//时间类型的数据，需要时间格式化
                SimpleDateFormat format = new SimpleDateFormat(cell.format());
                String dateStr = format.format((Date) javaValue);
                val = dateStr;
            } else if (javaValue instanceof Boolean && isReadConverterExp(cell)) {//boolean类型的。true = 1,false = 0;
                Map<String, Object> converter = (Map<String, Object>) cellCellAnnotationResolver.resolve(cell,cellCellAnnotationResolver.READ_CONVERTER_EXP);
                val = (String) converter.get(getConverterKey((Boolean) javaValue));
            } else if (javaValue instanceof Number && isReadConverterExp(cell)) {// 数字类型
                Map<String, Object> converter = (Map<String, Object>) cellCellAnnotationResolver.resolve(cell,cellCellAnnotationResolver.READ_CONVERTER_EXP);
                val = (String) converter.get(getConverterKey((Number) javaValue));
            } else if (javaValue instanceof String && isReadConverterExp(cell)) {//String类型
                Map<String, Object> converter = (Map<String, Object>) cellCellAnnotationResolver.resolve(cell,cellCellAnnotationResolver.READ_CONVERTER_EXP);
                val = (String) converter.get((String) javaValue);
            } else {//不需要 做类型转换的。
                val = javaValue.toString();
            }
        }
        return val;
    }

    private String getConverterKey (Boolean javaVal){
        if (javaVal) {
            return "1";
        } else {
            return "0";
        }
    }

    private String getConverterKey(Number number){
        return number.toString();
    }

    private String getConverterKeyByBool (Boolean javaVal){
        if (javaVal) {
            return "true";
        } else {
            return "false";
        }
    }

    public boolean isReadConverterExp(Cell cell){
        String readConverterExp = cell.readConverterExp();
        if (readConverterExp == null || readConverterExp.equals("")) {
            return false;
        } else {
            return true;
        }
    }






}
